package com.yingxin.yxerp.module.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yingxin.yx.framework.commons.constant.CommonConst;
import com.yingxin.yx.framework.commons.enums.BusinessType;
import com.yingxin.yx.framework.redis.lock.RedisLockSupport;
import com.yingxin.yxerp.module.common.BusinessTypeHelper;
import com.yingxin.yxerp.module.oplog.aop.OplogAnnotation;
import com.yingxin.yxerp.module.sys.entity.BusinessTypeSetting;
import com.yingxin.yxerp.module.sys.mapper.BusinessTypeSettingMapper;
import com.yingxin.yxerp.module.sys.service.IBusinessTypeSettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 每日编号 服务实现类
 * @author fanchao
 * @since 2022-01-16
 */

@Service
public class BusinessTypeSettingServiceImpl
        extends ServiceImpl<BusinessTypeSettingMapper, BusinessTypeSetting>
        implements IBusinessTypeSettingService {

    @Autowired
    private RedisLockSupport redisLockSupport;

    @OplogAnnotation(biz = BusinessType.BIZ_SETTING, id = "{{entity.id}}", action = "修改", desc = "")
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void update(BusinessTypeSetting entity) {
        updateById(entity);
        entity = getById(entity);
        BusinessTypeHelper.updateOne(entity.getCode(), entity.getName());
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public String next(BusinessType businessType) {
        try {
            redisLockSupport.lock("DailyNo_" + businessType.getType());
            QueryWrapper<BusinessTypeSetting> qw = new QueryWrapper<>();
            qw.lambda().eq(BusinessTypeSetting::getCode, businessType.getType());
            BusinessTypeSetting setting = getOne(qw);
            if (setting == null) {
                setting = new BusinessTypeSetting();
                setting.setCode(businessType.getType());
                setting.setName(businessType.getTypeName());
                setting.setDailyNo(0);
                setting.setDailyNoLength(3);
                setting.setDatePattern("yyMMdd");
                setting.setPrefix(businessType.getType());
                setting.setInvalidFlag("0");
                setting.setRecordDate(new Date());
            }
            // 今天 00:00
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            // recordDate < 今天 00:00 就把recordDate置为今天
            if (setting.getRecordDate().before(calendar.getTime())) {
                setting.setRecordDate(calendar.getTime());
                setting.setDailyNo(0);
            }
            // dailyNo = dailyNo + 1
            setting.setDailyNo(setting.getDailyNo() + 1);
            saveOrUpdate(setting);
            // prefix
            String prefix = setting.getPrefix();
            if (BusinessType.SX.equals(businessType)
                    || BusinessType.ZY.equals(businessType)
                    || BusinessType.DX.equals(businessType)
                    || BusinessType.LINE10101.equals(businessType)
                    || BusinessType.LINE10102.equals(businessType)
                    || BusinessType.LINE10103.equals(businessType)
                    || BusinessType.LINE10104.equals(businessType)
                    || BusinessType.LINE10201.equals(businessType)
                    || BusinessType.LINE10202.equals(businessType)
                    || BusinessType.LINE10203.equals(businessType)
                    || BusinessType.LINE10204.equals(businessType)
                    || BusinessType.LINE10205.equals(businessType)
                    || BusinessType.LINE10301.equals(businessType)
                    || BusinessType.LINE10302.equals(businessType)
                    || BusinessType.LINE10303.equals(businessType)
                    || BusinessType.LINE10304.equals(businessType)
                    || BusinessType.LINE10305.equals(businessType)) {
                prefix = "";
            }
            // recordDate
            SimpleDateFormat sdf = new SimpleDateFormat(setting.getDatePattern());
            // 补零长度
            String zeroFilling = "%0" + setting.getDailyNoLength() + "d";
            // prefix + recordDate + DailyNo
            return prefix + sdf.format(setting.getRecordDate()) + String.format(zeroFilling, setting.getDailyNo());
        } finally {
            redisLockSupport.unlock("DailyNo_" + businessType.getType());
        }
    }

    @Override
    public void cancelMaterialNo(BusinessType businessType, Date date) {
        // 查询
        QueryWrapper<BusinessTypeSetting> qw = new QueryWrapper<>();
        qw.lambda().eq(BusinessTypeSetting::getCode, businessType.getType());
        BusinessTypeSetting setting = getOne(qw);

        // date -> YYYYMMDD 000000
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        if (setting.getRecordDate().equals(calendar.getTime())) {
            UpdateWrapper<BusinessTypeSetting> uw = new UpdateWrapper<>();
            uw.setSql("daily_no = daily_no - 1 ");
            uw.lambda().eq(BusinessTypeSetting::getCode, businessType.getType());
            uw.lambda().eq(BusinessTypeSetting::getRecordDate, calendar.getTime());
            update(uw);
        }

    }

    @Override
    public String next(BusinessType businessType, String taxFlag) {
        if (CommonConst.TRUE.equals(taxFlag)) {
            return next(businessType).toUpperCase();
        } else {
            return next(businessType).toLowerCase();
        }
    }

}
